package com.iflytek.ci.qams.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.iflytek.ci.common.service.MailService;
import com.iflytek.ci.cpms.dao.ProjectDao;
import com.iflytek.ci.cpms.domain.Milestone;
import com.iflytek.ci.cpms.domain.Project;
import com.iflytek.ci.cpms.service.MilestoneService;
import com.iflytek.ci.cums.dao.AccountDao;
import com.iflytek.ci.cums.domain.Account;
import com.iflytek.ci.cums.service.impl.ShiroDbRealm;
import com.iflytek.ci.main.dao.AttachmentDao;
import com.iflytek.ci.main.dao.SerialNumberDao;
import com.iflytek.ci.main.domain.Attachment;
import com.iflytek.ci.main.dto.Macro;
import com.iflytek.ci.main.dto.MailContent;
import com.iflytek.ci.qams.dao.*;
import com.iflytek.ci.qams.domain.*;
import com.iflytek.ci.qams.service.ActionService;
import com.iflytek.ci.qams.service.FullTextService;
import com.iflytek.ci.qams.service.IssueService;
import com.iflytek.ci.qams.service.TypeService;
import com.iflytek.framework.pagination.PaginationCriteria;
import com.iflytek.framework.pagination.PaginationResult;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * issue service implements.
 * </p>
 * 
 * @author poplar.yfyang
 * @version 1.0 2012-11-03 6:58 PM
 * @since JDK 1.5
 */
@Service("IssueService")
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public class IssueServiceImpl implements IssueService {

	/** 反馈问题DAO */
	@Autowired
	private IssueDao issueDao;
	/** 项目DAO */
	@Autowired
	private ProjectDao projectDao;
	/** 流水ID */
	@Autowired
	private SerialNumberDao serialNumberDao;
	/** 附件服务 */
	@Autowired
	private AttachmentDao attachmentDao;
	/** 右键发送服务 */
	@Autowired
	private MailService mailService;
	/** 用户DAO */
	@Autowired
	private AccountDao accountDao;
	/** 请求DAO */
	@Autowired
	private ActionService actionService;
	/** 项目标签DAO */
	@Autowired
	private LabelDao labelDao;
	/** 优先级DAO */
	@Autowired
	private PriopityDao priopityDao;
	/** 全文检索服务 */
	@Autowired
	private FullTextService fullTextService;
	/** 批量添加action */
	@Autowired
	private TypeService typeService;
	/** 里程碑服务 */
	@Autowired
	private MilestoneService milestoneService;

	private static final Map<Integer, Integer> LABEL_PRIOPITY = Maps
			.newHashMap();

	static {
		/**
		 * 初始化
		 */
		LABEL_PRIOPITY.put(1, 2);
		LABEL_PRIOPITY.put(2, 3);
		LABEL_PRIOPITY.put(3, 5);
		LABEL_PRIOPITY.put(4, 4);
	}

	@Override
	public PaginationResult<Issue> find_issues(PaginationCriteria criteria,
			Map<String, Object> params) {
		ShiroDbRealm.ShiroUser shiro = (ShiroDbRealm.ShiroUser) SecurityUtils
				.getSubject().getPrincipal();
		if (SecurityUtils.getSubject().hasRole("Admin")) {
			return issueDao.issues_page_with_status(params, criteria);
		} else if (SecurityUtils.getSubject().hasRole("Leader")) {
			return issueDao.page_issue_leader_status(criteria,
					shiro.getLogin(), shiro.getName(), params);
		} else {
			return issueDao.page_issue_login_status(criteria, shiro.getLogin(),
					shiro.getName(), params);
		}
	}

	@Override
	public PaginationResult<Issue> get_all_issues(PaginationCriteria criteria) {
		ShiroDbRealm.ShiroUser shiro = (ShiroDbRealm.ShiroUser) SecurityUtils
				.getSubject().getPrincipal();
		if (SecurityUtils.getSubject().hasRole("Admin")) {
			return issueDao.pageIssue(criteria);
		} else if (SecurityUtils.getSubject().hasRole("Leader")) {
			return issueDao.page_getIssueByLeader(criteria, shiro.getLogin(),
					shiro.getName());
		} else {
			return issueDao.page_getIssueByLogin(criteria, shiro.getLogin(),
					shiro.getName());
		}

	}

	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	@Override
	public boolean create_project_issue_attachments(final Issue issue,
			List<Attachment> attachments) {
		if (create_project_issue(issue, issue.getPid())) {
			System.out.println(issue.getId());
			// 创建附件
			for (Attachment attachment1 : attachments) {
				System.out.println(attachment1);
				attachment1.setRfid(issue.getId());
			}
			attachmentDao.add_attachments(attachments);
			return true;
		} else {
			return false;
		}
	}

	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	@Override
	public boolean create_project_issue(final Issue issue, long project_id) {
		Project project = projectDao.project_with_id(project_id);
		if (Objects.equal(project, null)) {
			throw new RuntimeException("项目不存在");
		}
		issue.setPriopity(LABEL_PRIOPITY.get(issue.getIssuetype()));
		issue.setCreated(new Date());
		issue.setPid(project_id);
		issue.setPname(project.getName());

		// default label open
		issue.setIssuelabel(Macro.DEFAULT);
		// According to the problem of generating Key project.
		String key = generatingKey(project.getCode());
		issue.setPkey(key);
		if (Strings.isNullOrEmpty(issue.getAssignee())) {
			issue.setAssignee(project.getDev_leader());
			issue.setAssigneeName(accountDao.fromName(project.getDev_leader())
					.getName());
		}
		issueDao.new_issue(issue);
		project.setIssue_size(project.getIssue_size() + 1);
		projectDao.update_issue_size(project.getId(), project.getIssue_size());
		if (issue.getId() >= 0) {
			// 更新流水
			serialNumberDao.update_serial_number(project.getCode());
		} else {
			issueDao.remove_issues(new long[] { issueDao.issue_with_key(key)
					.getIssue_id() });
			return false;
		}
		// 执行全文检索
		fullTextService.create_index(issue);
		return true;
	}

	/**
	 * 生成问题KEy
	 * 
	 * @param project_key
	 *            项目KEY
	 * @return 问题KEY
	 */
	private String generatingKey(String project_key) {
		long sn = serialNumberDao.get_sn(project_key);
		return String.format("%s-%d", project_key, sn);
	}

	@Transactional
	@Override
	public void remove_issue(long[] id) {
		issueDao.remove_issues(id);
	}

	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	@Override
	public void update_issue(Issue issue) {
		issueDao.update_issue(issue);

	}

	@Override
	public Issue getFromId(long issue_id) {
		return issueDao.issue_with_id(issue_id);
	}

	@Override
	public PaginationResult<Issue> get_byp_id(PaginationCriteria criteria,
			long p_id) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("p_id", p_id);
		return issueDao.pageFindIssue(criteria, map);
	}

	@Override
	public IssueInformation from_key(String issue_key) {
		return issueDao.issue_with_key(issue_key);
	}

	@Override
	public void comment_size(int size, long id) {
		issueDao.issue_comment_size(size, id);
	}

	@Override
	public Issue getTop(long pid) {
		return issueDao.getTop(pid);
	}

	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	@Override
	public void update_assignee(String[] ids, String uname) {
		List<String> old_value = new ArrayList<String>();
		String to = accountDao.fromName(uname).getMail();
		List<Issue> issues = issueDao.get_issues_by_ids(ids);
		for (Issue issue : issues) {
			old_value.add(issue.getAssignee());
			final Project project = projectDao.project_with_id(issue.getPid());
			final Priopity priopity = priopityDao.get_priopity(issue
					.getPriopity());
			// 异步发送邮件
			final MailContent mailContent = new MailContent(issue, project,
					null, priopity);
			mailService.sendNotificationMail(mailContent, to);
		}
		issueDao.update_assignee(ids, uname);
		actionService.add_batch_action(ids, Macro.ACTION_ASSIGNEE, old_value,
				uname);
	}

	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	@Override
	public int update_issue_label(String[] issue_ids, int label) {
		List<String> old_value = new ArrayList<String>();
		List<Issue> issues = issueDao.get_issues_by_ids(issue_ids);
		for (Issue issue : issues) {
			old_value.add(labelDao.issue_label_with_id(issue.getIssuelabel())
					.getName());
		}
		actionService.add_batch_action(issue_ids, Macro.ACTION_LABEL,
				old_value, labelDao.issue_label_with_id(label).getName());
		return issueDao.update_issue_label(issue_ids, label);
	}

	@Override
	public List<Account> uinfo(String ids) {
		return issueDao.uinfo(ids);
	}

	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	@Override
	public void appoint_label(String id, int label) {
		actionService.add_action(Long.valueOf(id), Macro.ACTION_LABEL, labelDao
				.getByIssueId(Long.valueOf(id)).getName(), labelDao
				.issue_label_with_id(label).getName());
		issueDao.update_issue_label(new String[] { id }, label);
	}

	@Override
	public int get_count_todo(String login) {
		if (SecurityUtils.getSubject().hasRole("Admin")) {
			return issueDao.get_count_admin_todo();
		} else if (SecurityUtils.getSubject().hasRole("Leader")) {
			return issueDao.get_count_leader_todo(login);
		} else {
			return issueDao.get_count_assignee(login);
		}

	}

	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	@Override
	public void set_priopity(String[] ids, int priopity) {
		List<Issue> issues = issueDao.get_issues_by_ids(ids);
		List<String> old_value = new ArrayList<String>();
		for (Issue issue : issues) {
			old_value.add(priopityDao.get_priopity(issue.getPriopity())
					.getName());
		}
		issueDao.set_priopity(ids, priopity);
		actionService.add_batch_action(ids, Macro.ACTION_PRIOPITY, old_value,
				priopityDao.get_priopity(priopity).getName());
	}

	@Override
	public PaginationResult<Issue> page_getIssueByLogin(
			PaginationCriteria criteria, String login, String name) {
		return issueDao.page_getIssueByLogin(criteria, login, name);
	}

	@Override
	public PaginationResult<Issue> page_getIssueByLeader(
			PaginationCriteria criteria, String leader, String name) {
		return issueDao.page_getIssueByLeader(criteria, leader, name);
	}

	@Override
	public int get_number_reporte(String login) {
		return issueDao.get_number_reporte(login);
	}

	@Override
	public List<Issue> issue_assignee_order(String login) {
		if (SecurityUtils.getSubject().hasRole("Admin")) {
			return issueDao.get_issue_order();
		} else if (SecurityUtils.getSubject().hasRole("Leader")) {
			return issueDao.get_issue_leader_order(login);
		} else {
			return issueDao.issue_assignee_order(login);
		}
	}

	@Override
	public List<Issue> issue_reporter_order(String login) {
		return issueDao.issue_reporter_order(login);
	}

	@Override
	public PaginationResult<Issue> page_assignee_status(String login,
			String status, PaginationCriteria criteria) {
		return issueDao.page_assignee_status(login, status, criteria);
	}

	@Override
	public PaginationResult<Issue> page_reporte_status(
			PaginationCriteria criteria, String login) {
		return issueDao.page_reporte_status(criteria, login);
	}

	@Override
	public int issue_number_with_milestone_param(long milestone_id,
			String name, String value) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("name", name);
		map.put("value", value);
		return issueDao.issue_number_with_milestone_param(milestone_id, map);
	}

	@Override
	public List<Issue> issues_with_milestone(long milestone_id) {
		return issueDao.issues_with_milestone(milestone_id);
	}

	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	@Override
	public void update_issue_milestone(String[] issue_ids,String milestone){
		long[] ids=new long[issue_ids.length];
		for(int i=0;i<ids.length;i++){
			ids[i]=Long.valueOf(issue_ids[i]);
		}
		milestoneService.update_milestone_counts(Long.valueOf(milestone), ids);
		issueDao.assign_to_milestone(ids, milestoneService.get_milestone_id(Long.valueOf(milestone)));
	}

	@Override
	public List<Integer> count_with_project_status_type(long p_id) {
		List<IssueType> types = typeService.all_types();
		List<Integer> counts = new ArrayList<Integer>();
		for (IssueType type : types) {
			int count_open = issueDao.count_with_project_status_type(p_id,
					Macro.OPEN, type.getId());
			int count_all = issueDao.count_with_project_status_type(p_id,
					Macro.CLOSE, type.getId());// 后台查询结果为查询全部，而不是查询关闭的
			counts.add(count_open);
			counts.add(count_all);
		}
		return counts;
	}

	@Override
	public List<Integer> count_with_milestone_status(long milestone_id) {
		List<Integer> counts = new ArrayList<Integer>();
		int count_open = issueDao.count_milestone_status(milestone_id,
				Macro.OPEN);
		int count_close = issueDao.count_milestone_status(milestone_id,
				Macro.CLOSE);
		counts.add(count_open);
		counts.add(count_close);
		return counts;
	}

	@Override
	public PaginationResult<Issue> page_issue_milestone_list(
			PaginationCriteria criteria, Milestone milestone, String label) {
		Project project = projectDao.project_with_id(milestone.getProject());
		ShiroDbRealm.ShiroUser shiro = (ShiroDbRealm.ShiroUser) SecurityUtils
				.getSubject().getPrincipal();
		if (milestone.getOwner() == shiro.getId()
				|| SecurityUtils.getSubject().hasRole("Admin")
				|| StringUtils
						.equals(project.getDev_leader(), shiro.getLogin())
				|| StringUtils.equals(project.getLead(), shiro.getLogin())) {
			return issueDao.page_issue_milestone_all(criteria,
					milestone.getId(), label, shiro.getLogin());
		} else {
			return issueDao.page_issue_milestone_login(criteria,
					milestone.getId(), shiro.getLogin(), label);
		}
	}

	@Override
	public List<Issue> get_issue_project_order(long p_id) {
		return issueDao.get_issue_project_order(p_id);
	}

	@Override
	public PaginationResult<Issue> page_issue_project_list(
			PaginationCriteria criteria, Project project, String label) {
		ShiroDbRealm.ShiroUser shiro = (ShiroDbRealm.ShiroUser) SecurityUtils
				.getSubject().getPrincipal();
		if (StringUtils.equals(project.getDev_leader(), shiro.getLogin())
				|| StringUtils.equals(project.getLead(), shiro.getLogin())
				|| SecurityUtils.getSubject().hasRole("Admin")) {
			return issueDao.page_issue_project_all(criteria, project.getId(),
					shiro.getLogin(), label);
		} else {
			return issueDao.page_issue_project_login(criteria, project.getId(),
					shiro.getLogin(), label);
		}
	}

	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	@Override
	public void set_issue_fixed(String[] ids) {
		List<String> old_value = new ArrayList<String>();
		for (String id : ids) {
			old_value.add(Macro.ACTION_OPEN);
		}
		actionService.add_batch_action(ids, Macro.ACTION_FIXED, old_value,
				Macro.ACTION_FIXED);
		issueDao.close_or_open_issues(ids, Macro.FIXED);
	}

	@Override
	public PaginationResult<Issue> page_issue_fixed(PaginationCriteria criteria) {
		ShiroDbRealm.ShiroUser shiro = (ShiroDbRealm.ShiroUser) SecurityUtils
				.getSubject().getPrincipal();
		if (SecurityUtils.getSubject().hasRole("Admin")) {
			return issueDao.page_all_fixed(criteria);
		} else if (SecurityUtils.getSubject().hasRole("Leader")) {
			return issueDao.page_all_fixed_leader(criteria, shiro.getLogin());
		} else {
			return issueDao.page_all_fixed_user(criteria, shiro.getLogin());
		}
	}

	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	@Override
	public void close_open_issue(String[] ids, int status) {
		Date date = new Date();
		issueDao.update_updateTime(ids, date);
		List<String> old_value = new ArrayList<String>();
		long[]issue_ids=new long[ids.length];
		if (status == 0) {
			for (String id : ids) {
				
				if (issueDao.issue_with_id(Long.valueOf(id)).getIssuestatus() == 1) {
					old_value.add(Macro.ACTION_CLOSE);
				} else {
					old_value.add(Macro.ACTION_FIXED);
				}
			}
			actionService.add_batch_action(ids, Macro.ACTION_OPEN, old_value,
					Macro.ACTION_OPEN);
		    
		} else if (status == 1) {
			for (String id : ids) {
				if (issueDao.issue_with_id(Long.valueOf(id)).getIssuestatus() == 0) {
					old_value.add(Macro.ACTION_OPEN);
				} else {
					old_value.add(Macro.ACTION_FIXED);
				}
			}
			actionService.add_batch_action(ids, Macro.ACTION_CLOSE, old_value,
					Macro.ACTION_CLOSE);
		} else if (status == 2) {
			for (String id : ids) {
				if (issueDao.issue_with_id(Long.valueOf(id)).getIssuestatus() == 0) {
					old_value.add(Macro.ACTION_OPEN);
				} else {
					old_value.add(Macro.ACTION_CLOSE);
				}
			}
			actionService.add_batch_action(ids, Macro.ACTION_FIXED, old_value,
					Macro.ACTION_FIXED);
		}
		for(int i=0;i<ids.length;i++){
			issue_ids[i]=Long.valueOf(ids[i]);
		}
		issueDao.close_or_open_issues(ids, status);
		milestoneService.cate_count_update(issue_ids, status);
	}

	@Override
	public List<Integer> count_every_milestone_by_pid(String pid) {
		List<Milestone> milestones = milestoneService
				.get_milestones_project(Integer.valueOf(pid));
		List<Map<String, Integer>> map = new ArrayList<Map<String, Integer>>();
		List<Integer> ints = new ArrayList<Integer>();
		for (Milestone milestone : milestones) {
//			Map<String, Integer> map_mile = Maps.newHashMap();
//			 map_mile.put("open:",issueDao.count_milestone_status(milestone.getId(),
//			 Macro.OPEN));
//			 map_mile.put("close:",issueDao.count_milestone_status(milestone.getId(),
//			 Macro.CLOSE));
			ints.add(issueDao.count_milestone_status(milestone.getId(),
					Macro.OPEN));
			ints.add(issueDao.count_milestone_status(milestone.getId(),
					Macro.CLOSE));
//			 map.add(map_mile);
		}
		List<Integer> ints2 = new ArrayList<Integer>();
		for (int i = ints.size() - 1; i >= 0; i--) {
			ints2.add(ints.get(i));
		}
		return ints2;
	}

	@Override
	public PaginationResult<Issue> page_issue_by_conditions(
			SelectCondition conditions) {
		ShiroDbRealm.ShiroUser shiro = (ShiroDbRealm.ShiroUser) SecurityUtils
				.getSubject().getPrincipal();
		conditions.setLogin(shiro.getLogin());
		if (SecurityUtils.getSubject().hasRole("Admin")) {
			conditions.setRole("Admin");
		} else if (SecurityUtils.getSubject().hasRole("Leader")) {
			conditions.setRole("Leader");
		} else {
			conditions.setRole("User");
		}
		return issueDao.page_issue_conditions(conditions);
	}

	@Override
	public PaginationResult<Issue> page_by_pro_mile(long project_id,
			long milestone_id, PaginationCriteria criteria) {
		ShiroDbRealm.ShiroUser shiro = (ShiroDbRealm.ShiroUser) SecurityUtils
				.getSubject().getPrincipal();
		return issueDao.page_issue_pro_mile(project_id, milestone_id, shiro.getLogin(), criteria);
	}
}
